package org.easy.excel.configure;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import static org.easy.excel.configure.ParseThreadPoolConfigure.ThreadConstant.*;

/**
 * spring-security 支持的线程池配置
 *
 * @author 李坤
 * @date 2022/8/19 16:02
 */
@Configuration
public class ParseThreadPoolConfigure implements AsyncConfigurer {

    private final ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();

    @Override
    @Bean("asyncExecutor")
    public Executor getAsyncExecutor() {
        // 线程使用顺序：核心线程 > 缓冲队列 > 最大线程数
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();

        // 最大线程数
        taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        // 核心线程数
        taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        // 缓冲队列(执行缓冲任务的队列)
        taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        // 线程空闲时间(超时后将销毁非核线程)
        taskExecutor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
        // 线程名称前缀
        taskExecutor.setThreadNamePrefix(THREAD_NAME_PREFIX);
        // 线程拒绝策略(重试添加当前的任务直到成功)
        taskExecutor.setRejectedExecutionHandler(callerRunsPolicy);

        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }

    /**
     * 线程配置相关常量类
     *
     * @author 李坤
     * @date 2022/8/18 23:21
     */
    public abstract static class ThreadConstant {

        /**
         * Java 虚拟机可用的处理器数量
         */
        public static final int CPU_SIZE = Runtime.getRuntime().availableProcessors();

        /**
         * 核心线程数 == Java 虚拟机可用的处理器数量
         */
        public static final int CORE_POOL_SIZE = CPU_SIZE;

        /**
         * 线程空闲时间(超时后将销毁非核线程)
         */
        public static final int KEEP_ALIVE_SECONDS = 60 * 10;

        /**
         * 最大线程数 == 核心线程数 * 2
         */
        public static final int MAX_POOL_SIZE = CPU_SIZE << 3;

        /**
         * 缓冲队列长度(执行缓冲任务队列的长度)
         */
        public static final int QUEUE_CAPACITY = CPU_SIZE >> 1;

        /**
         * 线程空闲时间(超时后将心销毁非核线程)线程名称前缀
         */
        public static final String THREAD_NAME_PREFIX = "parseTask-";

    }
}
